﻿using System;
using System.Collections.Generic;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Text;

namespace Dycox.Linq.Data
{
    public static class LinqToSqlHelpers
    {
        //public static T FromKey<T>(this Table<T> table, object keyValue)
        //    where T: class
        //{
        //    return FromKey<T>(table, keyValue, false);
        //}

        //static Dictionary<Type, MetaTable> _metaTables = new Dictionary<Type, MetaTable>();

        //public static T FromKey<T>(this Table<T> table, object keyValue, bool throwError)
        //    where T : class
        //{
        //    if (table == null)
        //        throw new ArgumentNullException("table");
        //    if (keyValues == null || keyValues.Length == 0)
        //        throw new ArgumentNullException("keyValues");

        //    MetaTable metaTable;
        //    Type entityType = typeof(T);

        //    if (!_metaTables.TryGetValue(entityType, out metaTable))
        //    {
        //        metaTable = table.Context.Mapping.GetTable(entityType);
        //        _metaTables.Add(entityType, metaTable);
        //    }

        //    foreach (MetaDataMember member in metaTable.RowType.PersistentDataMembers)
        //    {
        //        //if (member.IsPrimaryKey
        //    }
            
        //}

        public static EntityChangeInfo GetChangeInfo(this DataContext dataContext, object entity)
        {
            if (dataContext == null)
                throw new ArgumentNullException("dataContext");
            if (entity == null)
                throw new ArgumentNullException("entity");

            ITable table = dataContext.GetTable(entity.GetType());
            object orgi = table.GetOriginalEntityState(entity);

            if (orgi == null)
                throw new ArgumentException(SR.GetString("cannot_find_original_state"));

            EntityChangeInfo info = new EntityChangeInfo();
            info.Original = orgi;
            info.New = entity;
            List<string> list = new List<string>();

            foreach (var m in table.GetModifiedMembers(entity))
            {
                list.Add(m.Member.Name);
            }

            info.MemberNames = list.ToArray();

            return info;
        }

        public static EntityKey GetKey(this DataContext dataContext, object entity)
        {
            if (dataContext == null)
                throw new ArgumentNullException("dataContext");
            if (entity == null)
                throw new ArgumentNullException("entity");

            MetaType type = dataContext.Mapping.GetTable(entity.GetType()).RowType;
            EntityKey key = new EntityKey();

            foreach (var m in type.IdentityMembers)
            {
                object v = m.MemberAccessor.GetBoxedValue(entity);
                key[m.Name] = v;
            }

            return key;
        }

        private static EntityKey GetKey(this ITable table, object entity)
        {
            if (table == null)
                throw new ArgumentNullException("table");
            if (entity == null)
                throw new ArgumentNullException("entity");

            return GetKey(table.Context, entity);
        }

        public static object GetEntity(this DataContext dataContext, EntityKey key, Type type)
        {
            if (dataContext == null)
                throw new ArgumentNullException("dataContext");
            if (key == null)
                throw new ArgumentNullException("key");
            if (type == null)
                throw new ArgumentNullException("type");

            return key.Execute(dataContext.GetTable(type));
        }
    }
}
